<script lang="ts" generic="T" setup>
import { computed, onMounted, reactive, ref, watch } from 'vue'
import type { TableProps } from 'ant-design-vue'
import { ColumnHeightOutlined, ReloadOutlined, SettingOutlined } from '@ant-design/icons-vue'
import type { CheckboxChangeEvent } from 'ant-design-vue/es/checkbox/interface'
import type { RequestTableEmits, RequestTableProps } from './typing'

const props = withDefaults(defineProps<RequestTableProps<T>>(), {
  showPagination: true,
  immediate: true,
  size: 'large',
  showIndex: false,
  rowKey: 'id',
  showSetting: true,
  showRefresh: true,
})

const emit = defineEmits<RequestTableEmits<T>>()

// 表格加载状态
const loading = ref(false)

// 表格数据
const tableData = ref<T[]>([])

// 分页配置
const pagination = reactive({
  current: 1,
  pageSize: 10,
  total: 0,
  showSizeChanger: true,
  showQuickJumper: true,
  showTotal: (total: number) => `共 ${total} 条`,
})

// 表格大小
const tableSize = ref<TableProps['size'][]>([props.size || 'middle'])

// 表格列设置
const columns = ref(props.columns)
const visibleColumns = ref(props.columns)
const dropdownVisible = ref(false)

// 修改列选择状态的类型定义
interface ColumnOption {
  label: string
  value: string
}

// 获取所有列的字段并转换为选项格式
const columnOptions = computed<ColumnOption[]>(() =>
  columns.value.map((col: { dataIndex: any }) => ({
    label: col.dataIndex,
    value: col.dataIndex,
  })),
)

// 列选择状态
const columnSelection = reactive({
  selectedFields: columnOptions.value.map(opt => opt.value),
  indeterminate: false,
  checkAll: true,
})

// 监听查询参数变化
watch(
  () => props.params,
  () => {
    if (props.params) {
      pagination.current = 1
      pagination.pageSize = 10
      fetchData()
    }
  },
  { deep: true },
)

// 获取表格数据
async function fetchData() {
  if (loading.value)
    return
  loading.value = true
  try {
    const params = {
      ...props.params,
      page: pagination.current,
      limit: pagination.pageSize,
    }

    const res = await props.request(params)
    tableData.value = res.list
    pagination.total = res.total
    pagination.current = res.page
    pagination.pageSize = res.limit

    emit('success', res)
  }
  catch (error) {
    emit('error', error)
  }
  finally {
    loading.value = false
  }
}

// 处理分页变化
function handleTableChange(pag: any) {
  pagination.current = pag.current
  pagination.pageSize = pag.pageSize
  fetchData()
}

// 处理表格大小变化
function handleSizeChange(size: TableProps['size']) {
  tableSize.value = [size]
}

// 修改处理列选择变化的函数
function handleColumnChange(checkedValues: (any)[]) {
  const selectedFields = checkedValues.map(v => v.toString())
  columnSelection.selectedFields = selectedFields
  visibleColumns.value = columns.value.filter((col: { dataIndex: any }) =>
    selectedFields.includes(col.dataIndex),
  )
}

// 修改处理全选的函数
function handleCheckAll(e: CheckboxChangeEvent) {
  const checked = e.target.checked
  const allValues = columnOptions.value.map(opt => opt.value)
  columnSelection.selectedFields = checked ? allValues : []
  visibleColumns.value = checked ? columns.value : []
}

// 重置列设置
function handleResetColumns() {
  columnSelection.selectedFields = columnOptions.value.map(opt => opt.value)
  visibleColumns.value = columns.value
}

// 刷新表格
function refresh() {
  fetchData()
}

// 初始化
onMounted(() => {
  if (props.immediate)
    fetchData()
})
</script>

<template>
  <div class="request-table">
    <div v-if="showSetting || showRefresh" class="table-toolbar" mb-4>
      <a-space>
        <a-tooltip v-if="showRefresh" title="刷新">
          <ReloadOutlined class="toolbar-icon" @click="refresh" />
        </a-tooltip>
        <a-tooltip v-if="showSetting" title="列设置">
          <a-dropdown v-model:open="dropdownVisible" trigger="click">
            <SettingOutlined class="toolbar-icon" />
            <template #overlay>
              <a-card :bordered="false" style="width: 200px">
                <template #title>
                  <a-checkbox
                    :checked="columnSelection.checkAll"
                    :indeterminate="columnSelection.indeterminate"
                    @change="handleCheckAll"
                  >
                    列展示
                  </a-checkbox>
                </template>
                <template #extra>
                  <a-button type="link" @click="handleResetColumns">
                    重置
                  </a-button>
                </template>
                <a-checkbox-group
                  v-model:value="columnSelection.selectedFields"
                  :options="columnOptions"
                  style="display: flex; flex-direction: column"
                  @change="handleColumnChange"
                />
              </a-card>
            </template>
          </a-dropdown>
        </a-tooltip>
        <a-tooltip title="密度">
          <a-dropdown trigger="click">
            <ColumnHeightOutlined class="toolbar-icon" />
            <template #overlay>
              <a-menu v-model:selected-keys="tableSize as string[]" @click="({ key }) => handleSizeChange(key as any)">
                <a-menu-item key="large">
                  默认
                </a-menu-item>
                <a-menu-item key="middle">
                  中等
                </a-menu-item>
                <a-menu-item key="small">
                  紧凑
                </a-menu-item>
              </a-menu>
            </template>
          </a-dropdown>
        </a-tooltip>
      </a-space>
    </div>

    <a-table
      :loading="loading"
      :columns="visibleColumns"
      :data-source="tableData"
      :pagination="showPagination ? pagination : false"
      :size="tableSize[0]"
      :row-key="rowKey"
      @change="handleTableChange"
    >
      <template v-if="$slots.bodyCell" #bodyCell="scope">
        <slot name="bodyCell" v-bind="scope" />
      </template>
    </a-table>
  </div>
</template>

<style lang="less" scoped>
.request-table {
  .table-toolbar {
    display: flex;
    justify-content: flex-end;

    .toolbar-icon {
      font-size: 16px;
      cursor: pointer;

      &:hover {
        color: #1890ff;
      }
    }
  }
}
</style>
